package com.wang.tool.mybatis;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.wang.tool.util.CommonUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * json存储对象
 * 1.db写入时配置typeHandler  可在写入时json化(自动检验是否是标准json)，兼容jsonArray以及jsonObject
 * insert into house
 * (location,price,data,type)
 * values(
 * #{location}
 * ,#{price}
 * ,#{data,typeHandler=test.dao.config.JsonTypeHandler}
 * ,#{type}
 * )
 * <p>
 * 2.db读取时返回json对象，指定javaType则按照类型解析，否则根据类属性类型解析
 * <resultMap id="BaseResultMap" type="test.dao.model.House">
 * <id property="id" column="id" jdbcType="BIGINT" />
 * <result property="location" column="location" jdbcType="VARCHAR"/>
 * <result property="price" column="price" jdbcType="INTEGER"/>
 * <result property="data" column="data" jdbcType="VARCHAR" javaType="test.dao.model.House" typeHandler="test.dao.config.JsonTypeHandler" />
 * <result property="type" column="type" jdbcType="INTEGER"/>
 * </resultMap>
 * <select id="select" resultMap="BaseResultMap">
 * select * from house order by id desc limit 0,3
 * </select>
 *
 * @author shaopeng
 */
public class JsonTypeHandler extends BaseTypeHandler<Object> {

    private Class<?> classType;

    public JsonTypeHandler(Class<?> classType) {
        this.classType = classType;
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null) {
            ps.setString(i, null);
            return;
        }
        String jsonString = parameter instanceof String ? ((String) parameter).trim() : JSON.toJSONString(parameter);
        if ("null".equals(jsonString)) {
            ps.setString(i, null);
            return;
        }
        if (!isValidJson(jsonString)) {
            throw new IllegalArgumentException("invalid jsonString," + jsonString);
        }
        ps.setString(i, jsonString);
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return deserializeObj(json);
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return deserializeObj(json);
    }


    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String json = cs.getString(columnIndex);
        return deserializeObj(json);
    }


    private Object deserializeObj(String json) {
        if (CommonUtil.isBlank(json)) {
            return null;
        }
        json = json.trim();
//        json=null  jsonValue为null
        Object jsonValue = JSON.parse(json);
        if (jsonValue == null) {
            return null;
        }
        if (jsonValue instanceof JSONArray) {
            return JSON.parseArray(json, classType);
        } else {
            return JSON.parseObject(json, classType);
        }
    }

    private boolean isValidJson(String jsonString) {
        try {
            JSON.parse(jsonString);
            return true;
        } catch (Throwable e) {
            return false;
        }
    }

}